package com.d2rv.guide;

import com.d2rv.model.GoalModelManager;
import com.d2rv.offscreen.OffScreen3D;
import com.d2rv.user.User;
import processing.core.PApplet;
import processing.core.PVector;

/**
 * This class is the manager of the class Goal which controls and draws the
 * current goal.
 *
 * @author Darrieutort A., Dupouy A., Rossignol L., Van Poucke A.
 */
public class GoalManager {

    private GoalModelManager goalmodelmanager;
    private int mode; // 1 dest, 2 parcours
    private GoalDestination goaldestination;
    private GoalCourse goalcourse;
    private PVector offScreenGuideMapCenter;
    private float ratio;

    /**
     * Default constructor.
     *
     * @param parent
     */
    public GoalManager(PApplet parent) {
        this.offScreenGuideMapCenter = new PVector(parent.width / 8 + (parent.width / 2 - parent.width / 8) / 2, parent.height / 2);
        this.ratio = (float) ((parent.width / 4) / 2);
        this.goalmodelmanager = new GoalModelManager(parent);
        this.goaldestination = new GoalDestination(this.goalmodelmanager.destinationModel());
        this.goalcourse = new GoalCourse(this.goalmodelmanager.courseModel());
        this.mode = 0;
    }

    /**
     * Updates the current mode of goal : 1 destination, 2 course.
     *
     * @param mode mode of goal
     */
    public void mode(int mode) {
        this.mode = mode;
    }

    /**
     * Returns the current goal to consider.
     *
     * @return the current goal 1,2 or null
     */
    public Goal currentGoal() {
        if (this.mode == 1) {
            this.goalcourse.init();
            return this.goaldestination;
        }
        if (this.mode == 2) {
            this.goaldestination.init();
            return this.goalcourse;
        }
        return null;
    }

    /**
     * Draws the current goal.
     *
     * @param parent
     */
    public void drawObjectif(OffScreen3D parent) {
        Goal obj = currentGoal();
        if (obj != null) {
            obj.draw(parent);
        }
    }

    /**
     * Draws the current goal of the guide offscreen.
     *
     * @param parent the current offscreen
     * @param userpos the user position
     */
    public void drawObjectifGuide(OffScreen3D parent, PVector userpos) {
        Goal obj = currentGoal();
        if (obj != null) {
            obj.drawGuide(parent, userpos);
        }
    }

    /**
     * Sets the new position of the goal.
     *
     * @param user User
     * @param mouseX mouseX
     * @param mouseY mouseY
     * @param zoom zoom factor of the camera
     */
    public void setCurrentGoalPosition(User user, float mouseX, float mouseY, float zoom) {
        PVector pos = positionScreenScene(user, mouseX, mouseY, zoom);
        this.currentGoal().position(pos);
    }

    /**
     * Computes and returns a position screen/scene by clicking on the guide
     * map.
     *
     * @param user User
     * @param mouseX mouseX
     * @param mouseY mouseY
     * @param zoom zoom factor of the camera
     *
     * @return the computed position screen/scene
     */
    public PVector positionScreenScene(User user, float mouseX, float mouseY, float zoom) {
        float scale = (float) (zoom * -40 * Math.tan((float) Math.PI / (float) 6.9));
        float scaleRatio = scale / this.ratio;

        mouseX -= this.offScreenGuideMapCenter.x - user.position().x * (this.ratio / scale);
        mouseY -= this.offScreenGuideMapCenter.y + user.position().z * (this.ratio / scale);

        return new PVector(mouseX * scaleRatio, 0, -mouseY * scaleRatio);
    }
}